<?php

//Controller chain data helper class;
class ControllerChainData {
    public $action;
    public $controller;
    public $vars;
    
    public function __construct($controller, $action, $vars=null) {
        $this->controller = $controller;
        $this->action = $action;
        $this->vars = $vars;
    }
} 

/**
 * Controller manager class
 *
 * This class allows for multiple contrllers to be chained together to be executed
 * after one another.
 */
class ControllerManager {
    private static $instance;
    private $currentController = 0;
    private $controllerArray;
    private $controllerArrayIndex = 0;
    
    /**
     * Constructor
     * @return null;
     */
    private function __construct() {
        $this->controllerArray = array();
        return;
    }
    
    /**
     * Singleton instance function
     * @return ControllerManager;
     */
    public static function inst() {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }
        return self::$instance;
    }

    /**
     * Registers a new controller into the chain for later execution.
     * @param string $controller controller name;
     * @param string $action  name;
     * @param array $vars additional parameters;
     * @return bool True on succesful registration; false on fail;
     */
    public function registerControllerIntoChain ($controller, $action, $vars=null) {
        $contpath = 'controllers/' . ucwords($controller) . '/' . ucwords($controller) . '.cont.php';
        if (file_exists($contpath)) {
            include_once($contpath);
            $this->controllerArray[$this->controllerArrayIndex++] = new ControllerChainData($controller, $action, $vars);
            return true;
        }
        return false;
    }

    /**
     * Fetches the next registered controller in the chain and increments.
     * @param string $controller Referenced controller name;
     * @param string $action Referenced action name;
     * @param array $vars Referenced additional parameters;
     * @return bool True on succesful fetch; false on last element;
     */
    private function fetchController(&$controller, &$action, &$vars) {
        if (isset($this->controllerArray[$this->currentController])) {
            $controller = $this->controllerArray[$this->currentController]->controller . 'Controller';
            $action = $this->controllerArray[$this->currentController]->action;
            $vars = $this->controllerArray[$this->currentController]->vars;
            $this->currentController++;
            return true;
        }
        return false;
    }
    
    /**
     * Begins execution of the controller chain.
     * @return bool True on completion of chain;
     */
    public function executeControllers() {
        while ($this->fetchController($controller, $action, $vars)) {
            try {
                $thiscontroller = new $controller();
                $thiscontroller->$action($vars);

            }
            catch (RecoverableException $e) {
                //Move on to the next controller in the sequence and display a status message;
            }
        }
        return true;
    }
}